From 4623e833aaf3a0e9bf948d3deabd32a9233d63ef Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 24 Mar 2005 21:44:30 +0000 Subject: [PATCH] bitkeeper revision 1.1236.43.4 (424334begQSfXEFH2X7nIwb4TohPsA) Fix TLB flushing on page type changes for SMP guests. Signed-off-by: Keir Fraser --- xen/arch/x86/mm.c | 15 +++++++++------ xen/common/page_alloc.c | 35 +++++++++++----------------------- xen/include/asm-x86/flushtlb.h | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index bd427ca0c5..ee661bc186 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1147,13 +1147,16 @@ int get_page_type(struct pfn_info *page, u32 type) * may be unnecessary (e.g., page was GDT/LDT) but those * circumstances should be very rare. */ - struct domain *d = page_get_owner(page); - if ( unlikely(NEED_FLUSH(tlbflush_time[d->exec_domain[0]-> - processor], - page->tlbflush_timestamp)) ) + struct exec_domain *ed; + unsigned long mask = 0; + for_each_exec_domain ( page_get_owner(page), ed ) + mask |= 1 << ed->processor; + mask = tlbflush_filter_cpuset(mask, page->tlbflush_timestamp); + + if ( unlikely(mask != 0) ) { - perfc_incr(need_flush_tlb_flush); - flush_tlb_cpu(d->exec_domain[0]->processor); + perfc_incrc(need_flush_tlb_flush); + flush_tlb_mask(mask); } /* We lose existing type, back pointer, and validity. */ diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 026217c5af..4cae1d2a63 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -470,43 +470,30 @@ void init_domheap_pages(unsigned long ps, unsigned long pe) struct pfn_info *alloc_domheap_pages(struct domain *d, unsigned int order) { struct pfn_info *pg; - unsigned long mask, flushed_mask, pfn_stamp, cpu_stamp; - int i, j; + unsigned long mask = 0; + int i; ASSERT(!in_irq()); if ( unlikely((pg = alloc_heap_pages(MEMZONE_DOM, order)) == NULL) ) return NULL; - flushed_mask = 0; for ( i = 0; i < (1 << order); i++ ) { - if ( (mask = (pg[i].u.free.cpu_mask & ~flushed_mask)) != 0 ) - { - pfn_stamp = pg[i].tlbflush_timestamp; - for ( j = 0; (mask != 0) && (j < smp_num_cpus); j++ ) - { - if ( mask & (1UL<page_alloc_lock); - for_each_exec_domain(d, ed) + for_each_exec_domain ( d, ed ) cpu_mask |= 1 << ed->processor; for ( i = 0; i < (1 << order); i++ ) diff --git a/xen/include/asm-x86/flushtlb.h b/xen/include/asm-x86/flushtlb.h index cebb78ebb5..5958b5f524 100644 --- a/xen/include/asm-x86/flushtlb.h +++ b/xen/include/asm-x86/flushtlb.h @@ -43,6 +43,26 @@ static inline int NEED_FLUSH(u32 cpu_stamp, u32 lastuse_stamp) (lastuse_stamp <= curr_time))); } +/* + * Filter the given set of CPUs, returning only those that may not have + * flushed their TLBs since @page_timestamp. + */ +static inline unsigned long tlbflush_filter_cpuset( + unsigned long cpuset, u32 page_timestamp) +{ + int i; + unsigned long remain; + + for ( i = 0, remain = ~0UL; (cpuset & remain) != 0; i++, remain <<= 1 ) + { + if ( (cpuset & (1UL << i)) && + !NEED_FLUSH(tlbflush_time[i], page_timestamp) ) + cpuset &= ~(1UL << i); + } + + return cpuset; +} + extern void new_tlbflush_clock_period(void); /* Read pagetable base. */ -- 2.30.2